/** @file scim_utility.h
 *  @brief various utility functions.
 */

/*
 * Smart Common Input Method
 * 
 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * $Id: scim_utility.h,v 1.36 2005/04/09 15:38:39 suzhe Exp $
 */

#ifndef __SCIM_UTILITY_H
#define __SCIM_UTILITY_H


/**
 * @addtogroup Accessories
 * @{
 */

#define SCIM_PATH_DELIM_STRING "/"
#define SCIM_PATH_DELIM        '/'

// UTF-8 <-> ucs4_t convert

/* Return code if invalid. (xxx_mbtowc, xxx_wctomb) */
#define RET_ILSEQ      0
/* Return code if only a shift sequence of n bytes was read. (xxx_mbtowc) */
#define RET_TOOFEW(n)  (-1-(n))
/* Return code if output buffer is too small. (xxx_wctomb, xxx_reset) */
#define RET_TOOSMALL   -1
/* Replacement character for invalid multibyte sequence or wide character. */
#define BAD_WCHAR ((ucs4_t) 0xfffd)
#define BAD_CHAR '?'

/**
 * @brief Convert an utf8 char sequence to ucs4.
 * 
 * @param pwc destination buffer to store the ucs4 code.
 * @param src source buffer contains the utf8 char sequence.
 * @param src_len the size of source buffer.
 *
 * @return number of chars in s actually converted.
 */ 
int utf8_mbtowc (ucs4_t *pwc, const unsigned char *src, int src_len);

/**
 * @brief Convert an ucs4 code to utf8 char sequence.
 *
 * @param dest destination buffer to store utf8 char sequence.
 * @param wc the ucs4 code to be converted.
 * @param dest_size the size of destination buffer.
 *
 * @return the number of bytes actually written into dest.
 */
int utf8_wctomb (unsigned char *dest, ucs4_t wc, int dest_size);

/**
 * @brief Convert an utf8 string to an ucs4 string.
 *
 * @param str source utf8 string.
 * @return the destination widestring.
 */
WideString utf8_mbstowcs (const String & str);

/**
 * @brief Convert an utf8 string to an ucs4 string.
 *
 * @param str source utf8 string.
 * @param len length of the source string.
 * @return the destination widestring.
 */
WideString utf8_mbstowcs (const char *str, int len = -1);

/**
 * @brief Convert an ucs4 string to an utf8 string.
 *
 * @param wstr source ucs4 string.
 *
 * @return the destination utf8 string.
 */
String utf8_wcstombs (const WideString & wstr);

/**
 * @brief Convert an ucs4 string to an utf8 string.
 *
 * @param wstr source ucs4 string.
 * @param len length of the source string.
 *
 * @return the destination utf8 string.
 */
String utf8_wcstombs (const ucs4_t *wstr, int len = -1);

/**
 * @brief Read a wide char from istream.
 *
 * The content in the istream are actually in utf-8 encoding.
 * 
 * @param is the stream to be read.
 *
 * @return if equal to 0 then got the end of the stream or error occurred.
 */
ucs4_t utf8_read_wchar (std::istream &is);

/**
 * @brief Write a wide char to ostream.
 *
 * The content written into the ostream will be converted into utf-8 encoding.
 *
 * @param os the stream to be written.
 * @param wc the wide char to be written to the stream.
 * @return the same stream object reference.
 */
std::ostream & utf8_write_wchar (std::ostream &os, ucs4_t wc);

/**
 * @brief Read a wide string from istream.
 *
 * The content in the istream are actually in utf-8 encoding.
 *
 * @param is the stream to be read.
 * @param delim the delimiter of the string.
 * @param rm_delim if the delim should be removed from the destination string.
 * @return the wide string read from the given stream.
 */
WideString utf8_read_wstring (std::istream &is, ucs4_t delim = (ucs4_t) '\n', bool rm_delim = true);

/**
 * @brief Write a wide string to ostream.
 *
 * The content written into the ostream will be converted into utf-8 encoding.
 *
 * @param os the stream to be written.
 * @param wstr the wide string to be written into the stream.
 * @return the same stream object reference.
 */
std::ostream & utf8_write_wstring (std::ostream &os, const WideString & wstr);

/**
 * @brief Convert an uint32 variable into a sequence of bytes.
 *
 * @param bytes the buffer to store the result.
 * @param n the variable to be converted.
 */
inline
void scim_uint32tobytes (unsigned char *bytes, uint32 n)
{
    bytes [0] = (unsigned char) ((n & 0xFF));
    bytes [1] = (unsigned char) ((n >> 8) & 0xFF);
    bytes [2] = (unsigned char) ((n >> 16) & 0xFF);
    bytes [3] = (unsigned char) ((n >> 24) & 0xFF);
}

/**
 * @brief Convert a sequence of bytes into an uint32 value.
 *
 * @param bytes the buffer contains the bytes to be converted.
 * @return the result uint32 value.
 */
inline
uint32 scim_bytestouint32 (const unsigned char *bytes)
{
    return  ((uint32) bytes [0])
            | (((uint32) bytes [1]) << 8)
            | (((uint32) bytes [2]) << 16)
            | (((uint32) bytes [3]) << 24);
}

/**
 * @brief Convert an uint16 variable into a sequence of bytes.
 *
 * @param bytes the buffer to store the result.
 * @param n the variable to be converted.
 */
inline
void scim_uint16tobytes (unsigned char *bytes, uint16 n)
{
    bytes [0] = (unsigned char) ((n & 0xFF));
    bytes [1] = (unsigned char) ((n >> 8) & 0xFF);
}

/**
 * @brief Convert a sequence of bytes into an uint16 value.
 *
 * @param bytes the buffer contains the bytes to be converted.
 * @return the result uint16 value.
 */
inline
uint16 scim_bytestouint16 (const unsigned char *bytes)
{
    return  ((uint16) bytes [0]) | (((uint16) bytes [1]) << 8);
}


/**
 * @brief Split string list into a string vector according to the delim char.
 *
 * @param vec the string vector to store the result.
 * @param str the string to be splitted.
 * @param delim the delimiter to split the strings.
 * @return the number of the strings in the result list.
 */
int scim_split_string_list (std::vector<String>& vec, const String& str, char delim = ',');

/**
  * @brief Get machine endian type
  * @return 1 little endian, 0 big endian
  */
bool scim_is_little_endian ();


#endif //__SCIM_UTILITY_H

